package com.laundry.user

import android.app.Application
import android.content.Context
import androidx.work.Configuration
import androidx.work.WorkManager
import com.laundry.user.data.local.DatabaseManager
import com.laundry.user.network.NetworkStateListener
import com.laundry.user.utils.CrashReportingTree
import com.laundry.user.utils.NotificationManager
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber
import javax.inject.Inject

@HiltAndroidApp
class LaundryApplication : Application(), Configuration.Provider {
    
    @Inject
    lateinit var networkStateListener: NetworkStateListener
    
    @Inject
    lateinit var databaseManager: DatabaseManager
    
    @Inject
    lateinit var notificationManager: NotificationManager
    
    override fun onCreate() {
        super.onCreate()
        
        initLogging()
        initDatabase()
        initNetworkMonitoring()
        initNotifications()
        initWorkManager()
        
        // 设置全局异常处理
        setupGlobalExceptionHandler()
    }
    
    private fun initLogging() {
        if (BuildConfig.DEBUG) {
            Timber.plant(Timber.DebugTree())
        } else {
            Timber.plant(CrashReportingTree())
        }
        
        Timber.d("LaundryApplication initialized")
    }
    
    private fun initDatabase() {
        databaseManager.initialize()
        Timber.d("Database initialized")
    }
    
    private fun initNetworkMonitoring() {
        networkStateListener.startListening()
        networkStateListener.addCallback { isConnected ->
            Timber.d("Network state changed: $isConnected")
            if (isConnected) {
                // 网络恢复时同步数据
                syncDataWhenNetworkAvailable()
            }
        }
        Timber.d("Network monitoring started")
    }
    
    private fun initNotifications() {
        notificationManager.createNotificationChannels()
        Timber.d("Notification channels created")
    }
    
    private fun initWorkManager() {
        // WorkManager会自动初始化，这里可以添加定期任务
        schedulePeriodicTasks()
        Timber.d("WorkManager tasks scheduled")
    }
    
    private fun setupGlobalExceptionHandler() {
        val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
        
        Thread.setDefaultUncaughtExceptionHandler { thread, exception ->
            Timber.e(exception, "Uncaught exception in thread ${thread.name}")
            
            // 记录崩溃信息
            recordCrash(exception)
            
            // 调用默认处理器
            defaultHandler?.uncaughtException(thread, exception)
        }
    }
    
    private fun syncDataWhenNetworkAvailable() {
        // 启动数据同步工作
        val syncWorkRequest = androidx.work.OneTimeWorkRequestBuilder<SyncDataWorker>()
            .setConstraints(
                androidx.work.Constraints.Builder()
                    .setRequiredNetworkType(androidx.work.NetworkType.CONNECTED)
                    .build()
            )
            .build()
        
        WorkManager.getInstance(this).enqueue(syncWorkRequest)
    }
    
    private fun schedulePeriodicTasks() {
        // 定期清理缓存
        val cleanupWorkRequest = androidx.work.PeriodicWorkRequestBuilder<CleanupWorker>(
            24, java.util.concurrent.TimeUnit.HOURS
        ).build()
        
        // 定期同步数据
        val syncWorkRequest = androidx.work.PeriodicWorkRequestBuilder<SyncDataWorker>(
            6, java.util.concurrent.TimeUnit.HOURS
        ).setConstraints(
            androidx.work.Constraints.Builder()
                .setRequiredNetworkType(androidx.work.NetworkType.CONNECTED)
                .setRequiresBatteryNotLow(true)
                .build()
        ).build()
        
        WorkManager.getInstance(this).apply {
            enqueueUniquePeriodicWork(
                "cleanup_work",
                androidx.work.ExistingPeriodicWorkPolicy.KEEP,
                cleanupWorkRequest
            )
            enqueueUniquePeriodicWork(
                "sync_work",
                androidx.work.ExistingPeriodicWorkPolicy.KEEP,
                syncWorkRequest
            )
        }
    }
    
    private fun recordCrash(exception: Throwable) {
        try {
            // 记录崩溃信息到本地文件或发送到服务器
            val crashInfo = CrashInfo(
                timestamp = System.currentTimeMillis(),
                exception = exception.toString(),
                stackTrace = exception.stackTraceToString(),
                appVersion = BuildConfig.VERSION_NAME,
                androidVersion = android.os.Build.VERSION.RELEASE,
                deviceModel = android.os.Build.MODEL
            )
            
            // 保存到本地
            saveCrashInfoLocally(crashInfo)
            
            // 如果有网络，立即发送
            if (networkStateListener.isNetworkAvailable()) {
                sendCrashInfoToServer(crashInfo)
            }
        } catch (e: Exception) {
            Timber.e(e, "Failed to record crash info")
        }
    }
    
    private fun saveCrashInfoLocally(crashInfo: CrashInfo) {
        val crashFile = java.io.File(filesDir, "crashes/${crashInfo.timestamp}.json")
        crashFile.parentFile?.mkdirs()
        
        val gson = com.google.gson.Gson()
        crashFile.writeText(gson.toJson(crashInfo))
    }
    
    private fun sendCrashInfoToServer(crashInfo: CrashInfo) {
        // 异步发送崩溃信息到服务器
        kotlinx.coroutines.GlobalScope.launch {
            try {
                // 实现发送逻辑
                Timber.d("Crash info sent to server")
            } catch (e: Exception) {
                Timber.e(e, "Failed to send crash info to server")
            }
        }
    }
    
    override fun getWorkManagerConfiguration(): Configuration {
        return Configuration.Builder()
            .setMinimumLoggingLevel(if (BuildConfig.DEBUG) android.util.Log.DEBUG else android.util.Log.INFO)
            .build()
    }
    
    override fun onTerminate() {
        super.onTerminate()
        networkStateListener.stopListening()
        Timber.d("LaundryApplication terminated")
    }
}

// 崩溃信息数据类
data class CrashInfo(
    val timestamp: Long,
    val exception: String,
    val stackTrace: String,
    val appVersion: String,
    val androidVersion: String,
    val deviceModel: String
)

// 数据同步Worker
class SyncDataWorker(
    context: Context,
    params: androidx.work.WorkerParameters
) : androidx.work.CoroutineWorker(context, params) {
    
    override suspend fun doWork(): Result {
        return try {
            Timber.d("Starting data sync...")
            
            // 实现数据同步逻辑
            // 1. 同步用户数据
            // 2. 同步服务数据
            // 3. 同步订单数据
            // 4. 上传本地缓存的数据
            
            Timber.d("Data sync completed successfully")
            Result.success()
        } catch (e: Exception) {
            Timber.e(e, "Data sync failed")
            Result.retry()
        }
    }
}

// 清理Worker
class CleanupWorker(
    context: Context,
    params: androidx.work.WorkerParameters
) : androidx.work.CoroutineWorker(context, params) {
    
    override suspend fun doWork(): Result {
        return try {
            Timber.d("Starting cleanup...")
            
            // 实现清理逻辑
            // 1. 清理过期缓存
            // 2. 清理临时文件
            // 3. 清理日志文件
            // 4. 压缩数据库
            
            cleanupExpiredCache()
            cleanupTempFiles()
            cleanupLogFiles()
            compressDatabase()
            
            Timber.d("Cleanup completed successfully")
            Result.success()
        } catch (e: Exception) {
            Timber.e(e, "Cleanup failed")
            Result.failure()
        }
    }
    
    private suspend fun cleanupExpiredCache() {
        // 清理过期的缓存文件
        val cacheDir = applicationContext.cacheDir
        val expiredTime = System.currentTimeMillis() - (7 * 24 * 60 * 60 * 1000) // 7天前
        
        cacheDir.listFiles()?.forEach { file ->
            if (file.lastModified() < expiredTime) {
                file.deleteRecursively()
                Timber.d("Deleted expired cache file: ${file.name}")
            }
        }
    }
    
    private suspend fun cleanupTempFiles() {
        // 清理临时文件
        val tempDir = java.io.File(applicationContext.filesDir, "temp")
        if (tempDir.exists()) {
            tempDir.deleteRecursively()
            Timber.d("Cleaned up temp directory")
        }
    }
    
    private suspend fun cleanupLogFiles() {
        // 清理旧的日志文件
        val logDir = java.io.File(applicationContext.filesDir, "logs")
        if (logDir.exists()) {
            val expiredTime = System.currentTimeMillis() - (30 * 24 * 60 * 60 * 1000) // 30天前
            
            logDir.listFiles()?.forEach { file ->
                if (file.lastModified() < expiredTime) {
                    file.delete()
                    Timber.d("Deleted expired log file: ${file.name}")
                }
            }
        }
    }
    
    private suspend fun compressDatabase() {
        // 压缩数据库
        try {
            // 实现数据库压缩逻辑
            Timber.d("Database compressed successfully")
        } catch (e: Exception) {
            Timber.e(e, "Failed to compress database")
        }
    }
}
